<?php
abstract class callback_module extends module {
	const		PRIORITY_NORMAL = 0;
	protected	$callback = null;
	protected	$parameters;
	public function __construct($callback, array $parameters = array(), $priority = self::PRIORITY_NORMAL) {
		$this->name = get_class($this);
		if (is_array($callback) and !is_object($callback[0]))
			throw new Exception("Invalid callback object specified for $this->name",018);
		if (is_array($callback) and !method_exists($callback[0], $callback[1]))
			throw new Exception("Invalid callback method specified for $this->name",019);
		if (is_string($callback) and !function_exists($callback))
			throw new Exception("Invalid callback function specified for $this->name",020);
		if (!is_array($parameters))
			throw new Exception("Invalid parameters parameter for $this->name",021);
		$this->callback = $callback;
		if (!isset($GLOBALS['callbacks'][$this->name]))
			$GLOBALS['callbacks'][$this->name] = array();
		if ($priority)
			$GLOBALS['callbacks'][$this->name][($priority * -1)] =& $this;
		else
			$GLOBALS['callbacks'][$this->name][] =& $this;
		$this->parameters = $parameters;
	}
	static function run($name, $parameters = array()) {
		if (!array_key_exists($name,$GLOBALS['callbacks'])) return null;
		foreach ($GLOBALS['callbacks'][$name] as &$callback) {
			$result = $callback->execute($parameters);
			if ($result) return $result;
		}
	}
	public function execute($parameters = array()) {
		return call_user_func_array($this->callback,array_merge($this->parameters, $parameters));
	}
	public function __destruct() {
		foreach ($GLOBALS['callbacks'][$this->name] as $key => &$callback) {
			if ($callback !== $this)
				continue;
			unset($GLOBALS['callbacks'][$this->name][$key]);
			return true;
		}
		return false;
	}
}
?>
